package com.easipass;
import com.easipass.model.DiffLine;
import com.easipass.model.DiffType;
import com.easipass.util.FileUtils;

import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javax.swing.text.DefaultHighlighter;
import javax.swing.text.Highlighter;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.io.IOException;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
import java.awt.Toolkit;
import java.awt.datatransfer.StringSelection;
import java.awt.Desktop;
import java.net.URI;


public class FileComparatorUI extends JFrame {
    private JTextArea leftTextArea;
    private JTextArea rightTextArea;
    private JButton compareButton;
    private JButton fullOverrideButton;
    private JList<DiffLine> diffList;
    private DefaultListModel<DiffLine> listModel;
    private JButton useLeftButton;
    private JButton useRightButton;
    // 新增：将发送按钮设为成员变量
    private JButton sendToDoubaoButton;

    // 新增组件
    private JTextField leftFilePathField;
    private JTextField rightFilePathField;
    private JButton leftFileSelectButton;
    private JButton rightFileSelectButton;
    private JTextField searchField;
    private JComboBox<String> searchTypeComboBox;
    private JButton searchButton;
    private JCheckBox caseSensitiveCheckBox;

    private List<DiffLine> currentDiff;
    private FileComparator comparator;

    private Path leftFilePath;
    private Path rightFilePath;

    public FileComparatorUI() {
        comparator = new FileComparator();
        initializeUI();
    }

    private void initializeUI() {
        setTitle("文件对比工具 - 增强版");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setSize(1400, 900);
        setLocationRelativeTo(null);

        // 主面板
        JPanel mainPanel = new JPanel(new BorderLayout(10, 10));
        mainPanel.setBorder(new EmptyBorder(10, 10, 10, 10));

        // 顶部文件选择面板
        JPanel fileSelectionPanel = createFileSelectionPanel();
        mainPanel.add(fileSelectionPanel, BorderLayout.NORTH);

        // 中间对比面板
        JSplitPane compareSplitPane = createComparePanel();
        mainPanel.add(compareSplitPane, BorderLayout.CENTER);

        // 底部操作面板
        JPanel actionPanel = createActionPanel();
        mainPanel.add(actionPanel, BorderLayout.SOUTH);

        setContentPane(mainPanel);
    }

    private JPanel createFileSelectionPanel() {
        JPanel panel = new JPanel(new GridLayout(3, 1, 5, 5));

        // 第一行：左边文件选择
        JPanel leftFilePanel = new JPanel(new BorderLayout(5, 5));
        leftFilePanel.setBorder(BorderFactory.createTitledBorder("左边文件"));
        leftFilePathField = new JTextField();
        leftFilePathField.setEditable(false);
        leftFileSelectButton = new JButton("选择文件");
        leftFileSelectButton.addActionListener(e -> selectLeftFile());

        leftFilePanel.add(leftFilePathField, BorderLayout.CENTER);
        leftFilePanel.add(leftFileSelectButton, BorderLayout.EAST);

        // 第二行：右边文件选择
        JPanel rightFilePanel = new JPanel(new BorderLayout(5, 5));
        rightFilePanel.setBorder(BorderFactory.createTitledBorder("右边文件"));
        rightFilePathField = new JTextField();
        rightFilePathField.setEditable(false);
        rightFileSelectButton = new JButton("选择文件");
        rightFileSelectButton.addActionListener(e -> selectRightFile());

        rightFilePanel.add(rightFilePathField, BorderLayout.CENTER);
        rightFilePanel.add(rightFileSelectButton, BorderLayout.EAST);

        // 第三行：操作按钮和搜索
        JPanel controlPanel = new JPanel(new BorderLayout(5, 5));

        // 左边：对比按钮
        JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
        compareButton = new JButton("开始对比");
        compareButton.addActionListener(this::compareFiles);
        compareButton.setEnabled(false);

        fullOverrideButton = new JButton("右边完全覆盖左边");
        fullOverrideButton.addActionListener(this::fullOverride);
        fullOverrideButton.setEnabled(false);

        buttonPanel.add(compareButton);
        buttonPanel.add(fullOverrideButton);

        // 右边：搜索面板
        JPanel searchPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
        searchPanel.setBorder(BorderFactory.createTitledBorder("搜索"));

        searchField = new JTextField(15);
        searchTypeComboBox = new JComboBox<>(new String[]{"模糊查询", "正则表达式", "精确匹配"});
        caseSensitiveCheckBox = new JCheckBox("区分大小写");
        searchButton = new JButton("搜索");
        searchButton.addActionListener(this::performSearch);

        searchPanel.add(new JLabel("搜索:"));
        searchPanel.add(searchField);
        searchPanel.add(searchTypeComboBox);
        searchPanel.add(caseSensitiveCheckBox);
        searchPanel.add(searchButton);

        controlPanel.add(buttonPanel, BorderLayout.WEST);
        controlPanel.add(searchPanel, BorderLayout.EAST);

        panel.add(leftFilePanel);
        panel.add(rightFilePanel);
        panel.add(controlPanel);

        return panel;
    }

    private JSplitPane createComparePanel() {
        JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);

        // 左边文件面板（包含搜索高亮）
        JPanel leftPanel = new JPanel(new BorderLayout());
        leftPanel.setBorder(BorderFactory.createTitledBorder("左边文件内容"));
        leftTextArea = new JTextArea();
        leftTextArea.setEditable(false);
        leftTextArea.setFont(new Font("Monospaced", Font.PLAIN, 14));

        // 添加行号
        JScrollPane leftScrollPane = new JScrollPane(leftTextArea);
        leftScrollPane.setRowHeaderView(new LineNumberTable(leftTextArea));

        leftPanel.add(leftScrollPane, BorderLayout.CENTER);

        // 右边文件面板（包含搜索高亮）
        JPanel rightPanel = new JPanel(new BorderLayout());
        rightPanel.setBorder(BorderFactory.createTitledBorder("右边文件内容"));
        rightTextArea = new JTextArea();
        rightTextArea.setEditable(false);
        rightTextArea.setFont(new Font("Monospaced", Font.PLAIN, 14));

        JScrollPane rightScrollPane = new JScrollPane(rightTextArea);
        rightScrollPane.setRowHeaderView(new LineNumberTable(rightTextArea));

        rightPanel.add(rightScrollPane, BorderLayout.CENTER);

        splitPane.setLeftComponent(leftPanel);
        splitPane.setRightComponent(rightPanel);
        splitPane.setDividerLocation(0.5);

        return splitPane;
    }

    private JPanel createActionPanel() {
        JPanel panel = new JPanel(new BorderLayout());

        // 差异列表
        listModel = new DefaultListModel<DiffLine>();
        diffList = new JList<DiffLine>(listModel);
        diffList.setCellRenderer(new DiffListCellRenderer());
        diffList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);

        JScrollPane listScrollPane = new JScrollPane(diffList);
        listScrollPane.setBorder(BorderFactory.createTitledBorder("差异列表 (选择行进行操作)"));
        listScrollPane.setPreferredSize(new Dimension(0, 150));

        // 操作按钮
        JPanel buttonPanel = new JPanel(new FlowLayout());
        useLeftButton = new JButton("使用左边覆盖右边");
        useRightButton = new JButton("使用右边覆盖左边");
        // 新增发送到豆包分析的按钮
        sendToDoubaoButton = new JButton("发送到豆包分析");
        sendToDoubaoButton.addActionListener(e -> sendDiffToDoubao());

        useLeftButton.addActionListener(e -> overrideLine(true));
        useRightButton.addActionListener(e -> overrideLine(false));
        sendToDoubaoButton.setEnabled(false); // 初始禁用
        useLeftButton.setEnabled(false);
        useRightButton.setEnabled(false);

        buttonPanel.add(useLeftButton);
        buttonPanel.add(useRightButton);
        buttonPanel.add(sendToDoubaoButton); // 添加到按钮面板

        panel.add(listScrollPane, BorderLayout.CENTER);
        panel.add(buttonPanel, BorderLayout.SOUTH);

        return panel;
    }

    private void sendDiffToDoubao() {
        if (currentDiff == null || currentDiff.isEmpty()) {
            JOptionPane.showMessageDialog(this, "没有可复制的差异内容", "提示", JOptionPane.INFORMATION_MESSAGE);
            return;
        }

        // 1. 构建差异列表内容并复制到剪贴板
        StringBuilder diffContent = new StringBuilder();
        diffContent.append("文件差异对比结果：\n");
        diffContent.append("左边文件：").append(leftFilePath != null ? leftFilePath.getFileName() : "未知文件").append("\n");
        diffContent.append("右边文件：").append(rightFilePath != null ? rightFilePath.getFileName() : "未知文件").append("\n\n");

        for (DiffLine line : currentDiff) {
            if (line.getType() != DiffType.SAME) { // 只复制有差异的行
                diffContent.append(String.format("行号 L%d R%d - 类型：%s\n",
                        line.getLeftLineNumber() > 0 ? line.getLeftLineNumber() : 0,
                        line.getRightLineNumber() > 0 ? line.getRightLineNumber() : 0,
                        line.getType()));

                if (!line.getLeftContent().isEmpty()) {
                    diffContent.append("左边内容：").append(line.getLeftContent()).append("\n");
                }
                if (!line.getRightContent().isEmpty()) {
                    diffContent.append("右边内容：").append(line.getRightContent()).append("\n");
                }
                diffContent.append("----------------------------------------\n");
            }
        }

        // 复制到剪贴板
        StringSelection selection = new StringSelection(diffContent.toString());
        Toolkit.getDefaultToolkit().getSystemClipboard().setContents(selection, null);

        // 2. 打开豆包网站
        try {
            Desktop desktop = Desktop.getDesktop();
            if (desktop.isSupported(Desktop.Action.BROWSE)) {
                desktop.browse(new URI("https://www.doubao.com"));
            } else {
                JOptionPane.showMessageDialog(this, "无法打开浏览器，请手动访问 https://www.doubao.com",
                        "提示", JOptionPane.INFORMATION_MESSAGE);
            }
        } catch (Exception e) {
            JOptionPane.showMessageDialog(this, "打开网页失败：" + e.getMessage(),
                    "错误", JOptionPane.ERROR_MESSAGE);
            e.printStackTrace();
        }
    }


    private void selectLeftFile() {
        JFileChooser fileChooser = new JFileChooser();
        fileChooser.setDialogTitle("选择左边文件");

        if (fileChooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) {
            leftFilePath = fileChooser.getSelectedFile().toPath();
            leftFilePathField.setText(leftFilePath.toString());
            updateCompareButtonState();
        }
    }

    private void selectRightFile() {
        JFileChooser fileChooser = new JFileChooser();
        fileChooser.setDialogTitle("选择右边文件");

        if (fileChooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) {
            rightFilePath = fileChooser.getSelectedFile().toPath();
            rightFilePathField.setText(rightFilePath.toString());
            updateCompareButtonState();
        }
    }

    private void updateCompareButtonState() {
        boolean bothFilesSelected = leftFilePath != null && rightFilePath != null;
        compareButton.setEnabled(bothFilesSelected);
    }

    private void compareFiles(ActionEvent e) {
        if (leftFilePath == null || rightFilePath == null) {
            JOptionPane.showMessageDialog(this, "请先选择两个文件", "警告", JOptionPane.WARNING_MESSAGE);
            return;
        }

        try {
            List<String> leftLines = FileUtils.readFileLines(leftFilePath);
            List<String> rightLines = FileUtils.readFileLines(rightFilePath);

            // 显示原始文件内容
            leftTextArea.setText(joinLines(leftLines));
            rightTextArea.setText(joinLines(rightLines));

            // 清除搜索高亮
            clearHighlights();

            // 计算差异
            currentDiff = comparator.compareFiles(leftLines, rightLines);
            updateDiffList();

            // 启用相关按钮
            fullOverrideButton.setEnabled(true);
            updateSendToDoubaoButtonState();

        } catch (IOException ex) {
            JOptionPane.showMessageDialog(this, "读取文件失败: " + ex.getMessage(),
                    "错误", JOptionPane.ERROR_MESSAGE);
        }
    }

    // 新增：更新发送到豆包按钮的状态
    private void updateSendToDoubaoButtonState() {
        boolean hasDifferences = currentDiff != null && !currentDiff.isEmpty() &&
                currentDiff.stream().anyMatch(line -> line.getType() != DiffType.SAME);
        sendToDoubaoButton.setEnabled(hasDifferences);
    }

    private void performSearch(ActionEvent e) {
        String searchText = searchField.getText().trim();
        if (searchText.isEmpty()) {
            JOptionPane.showMessageDialog(this, "请输入搜索内容", "提示", JOptionPane.INFORMATION_MESSAGE);
            return;
        }

        String searchType = (String) searchTypeComboBox.getSelectedItem();
        boolean caseSensitive = caseSensitiveCheckBox.isSelected();

        try {
            clearHighlights();

            // 在左右两个文本区域中搜索
            searchInTextArea(leftTextArea, searchText, searchType, caseSensitive, Color.YELLOW);
            searchInTextArea(rightTextArea, searchText, searchType, caseSensitive, Color.YELLOW);

            // 在差异列表中搜索
            searchInDiffList(searchText, searchType, caseSensitive);

        } catch (PatternSyntaxException ex) {
            JOptionPane.showMessageDialog(this, "正则表达式语法错误: " + ex.getMessage(),
                    "错误", JOptionPane.ERROR_MESSAGE);
        }
    }

    private void searchInTextArea(JTextArea textArea, String searchText, String searchType,
                                  boolean caseSensitive, Color highlightColor) {
        String content = textArea.getText();
        if (content.isEmpty()) return;

        Highlighter highlighter = textArea.getHighlighter();
        highlighter.removeAllHighlights();

        String patternText;
        switch (searchType) {
            case "模糊查询":
                // 将搜索文本转换为模糊匹配模式
                patternText = ".*?" + Pattern.quote(searchText) + ".*?";
                break;
            case "正则表达式":
                patternText = searchText;
                break;
            case "精确匹配":
            default:
                patternText = Pattern.quote(searchText);
                break;
        }

        Pattern pattern;
        if (caseSensitive) {
            pattern = Pattern.compile(patternText);
        } else {
            pattern = Pattern.compile(patternText, Pattern.CASE_INSENSITIVE);
        }

        java.util.regex.Matcher matcher = pattern.matcher(content);
        while (matcher.find()) {
            try {
                highlighter.addHighlight(matcher.start(), matcher.end(),
                        new DefaultHighlighter.DefaultHighlightPainter(highlightColor));
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }
    }

    private void searchInDiffList(String searchText, String searchType, boolean caseSensitive) {
        if (listModel.isEmpty()) return;

        List<Integer> matchedIndices = new ArrayList<>();

        for (int i = 0; i < listModel.size(); i++) {
            DiffLine line = listModel.get(i);
            String leftContent = line.getLeftContent();
            String rightContent = line.getRightContent();

            boolean leftMatch = matchesSearch(leftContent, searchText, searchType, caseSensitive);
            boolean rightMatch = matchesSearch(rightContent, searchText, searchType, caseSensitive);

            if (leftMatch || rightMatch) {
                matchedIndices.add(i);
            }
        }

        if (!matchedIndices.isEmpty()) {
            // 选择第一个匹配项
            diffList.setSelectedIndex(matchedIndices.get(0));
            // 滚动到选择的位置
            diffList.ensureIndexIsVisible(matchedIndices.get(0));

            if (matchedIndices.size() > 1) {
                JOptionPane.showMessageDialog(this,
                        "找到 " + matchedIndices.size() + " 个匹配项",
                        "搜索结果", JOptionPane.INFORMATION_MESSAGE);
            }
        } else {
            JOptionPane.showMessageDialog(this, "未找到匹配项",
                    "搜索结果", JOptionPane.INFORMATION_MESSAGE);
        }
    }

    private boolean matchesSearch(String content, String searchText, String searchType, boolean caseSensitive) {
        if (content == null || content.isEmpty()) return false;

        String textToSearch = caseSensitive ? content : content.toLowerCase();
        String searchPattern = caseSensitive ? searchText : searchText.toLowerCase();

        switch (searchType) {
            case "模糊查询":
                return textToSearch.contains(searchPattern);
            case "正则表达式":
                try {
                    Pattern pattern = caseSensitive ?
                            Pattern.compile(searchText) :
                            Pattern.compile(searchText, Pattern.CASE_INSENSITIVE);
                    return pattern.matcher(content).find();
                } catch (PatternSyntaxException e) {
                    throw e;
                }
            case "精确匹配":
            default:
                return textToSearch.equals(searchPattern);
        }
    }

    private void clearHighlights() {
        leftTextArea.getHighlighter().removeAllHighlights();
        rightTextArea.getHighlighter().removeAllHighlights();
    }

    private String joinLines(List<String> lines) {
        StringBuilder sb = new StringBuilder();
        for (String line : lines) {
            sb.append(line).append("\n");
        }
        return sb.toString();
    }

    private void updateDiffList() {
        listModel.clear();
        for (DiffLine line : currentDiff) {
            listModel.addElement(line);
        }

        // 启用操作按钮
        useLeftButton.setEnabled(true);
        useRightButton.setEnabled(true);
        // 更新发送按钮状态
        updateSendToDoubaoButtonState();
    }

    private void overrideLine(boolean useLeft) {
        int selectedIndex = diffList.getSelectedIndex();
        if (selectedIndex == -1) {
            JOptionPane.showMessageDialog(this, "请先选择要操作的行");
            return;
        }

        DiffLine selectedLine = currentDiff.get(selectedIndex);
        if (selectedLine.getType() == DiffType.SAME) {
            JOptionPane.showMessageDialog(this, "该行内容相同，无需操作");
            return;
        }

        // 应用覆盖操作
        currentDiff = comparator.applyLineOverride(currentDiff, selectedIndex, useLeft);
        updateDiffList();
        updateTextAreas();
    }

    private void fullOverride(ActionEvent e) {
        if (currentDiff == null) return;

        int result = JOptionPane.showConfirmDialog(this,
                "确定要用右边文件完全覆盖左边文件吗？此操作不可撤销。",
                "确认覆盖", JOptionPane.YES_NO_OPTION);

        if (result == JOptionPane.YES_OPTION) {
            try {
                List<String> newLeftContent = comparator.fullOverrideRightToLeft(currentDiff);
                FileUtils.writeFileLines(leftFilePath, newLeftContent);

                // 重新加载并对比
                compareFiles(e);

                JOptionPane.showMessageDialog(this, "覆盖完成！");

            } catch (IOException ex) {
                JOptionPane.showMessageDialog(this, "写入文件失败: " + ex.getMessage(),
                        "错误", JOptionPane.ERROR_MESSAGE);
            }
        }
    }

    private void updateTextAreas() {
        StringBuilder leftContent = new StringBuilder();
        StringBuilder rightContent = new StringBuilder();

        for (DiffLine line : currentDiff) {
            if (!line.getLeftContent().isEmpty()) {
                leftContent.append(line.getLeftContent()).append("\n");
            }
            if (!line.getRightContent().isEmpty()) {
                rightContent.append(line.getRightContent()).append("\n");
            }
        }

        leftTextArea.setText(leftContent.toString());
        rightTextArea.setText(rightContent.toString());
    }

    // 自定义列表单元格渲染器，用于颜色标记
    private class DiffListCellRenderer extends DefaultListCellRenderer {
        @Override
        public Component getListCellRendererComponent(JList<?> list, Object value,
                                                      int index, boolean isSelected, boolean cellHasFocus) {
            super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);

            if (value instanceof DiffLine) {
                DiffLine line = (DiffLine) value;
                setText(formatLineDisplay(line));

                // 设置颜色
                switch (line.getType()) {
                    case SAME:
                        setBackground(isSelected ? new Color(200, 200, 255) : Color.WHITE);
                        break;
                    case DIFFERENT:
                        setBackground(isSelected ? new Color(255, 200, 200) : new Color(255, 230, 230));
                        break;
                    case LEFT_ONLY:
                        setBackground(isSelected ? new Color(255, 220, 200) : new Color(255, 240, 230));
                        break;
                    case RIGHT_ONLY:
                        setBackground(isSelected ? new Color(200, 255, 200) : new Color(230, 255, 230));
                        break;
                }
            }

            return this;
        }

        private String formatLineDisplay(DiffLine line) {
            return String.format("L%-3d | R%-3d | %s | %s",
                    line.getLeftLineNumber() > 0 ? line.getLeftLineNumber() : 0,
                    line.getRightLineNumber() > 0 ? line.getRightLineNumber() : 0,
                    line.getLeftContent().isEmpty() ? "---" : line.getLeftContent(),
                    line.getRightContent().isEmpty() ? "---" : line.getRightContent());
        }
    }

    // 行号表格
    private class LineNumberTable extends JComponent {
        private final JTextArea textArea;
        private final Font font;

        public LineNumberTable(JTextArea textArea) {
            this.textArea = textArea;
            this.font = new Font("Monospaced", Font.PLAIN, 14);
            setPreferredSize(new Dimension(40, 0));
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);

            g.setColor(Color.LIGHT_GRAY);
            g.fillRect(0, 0, getWidth(), getHeight());
            g.setColor(Color.BLACK);
            g.setFont(font);

            int lineHeight = textArea.getFontMetrics(font).getHeight();
            int startLine = 1;
            int y = lineHeight;

            String[] lines = textArea.getText().split("\n");
            for (int i = 0; i < lines.length; i++) {
                g.drawString(String.valueOf(startLine + i), 5, y);
                y += lineHeight;
            }
        }
    }
}
